package cn.jtfadmin.core.config.file;


import cn.jtfadmin.base.filesystem.annos.File;
import cn.jtfadmin.base.filesystem.config.FileResourceConfig;
import cn.jtfadmin.base.filesystem.config.FileResourceConfigDTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;

import javax.persistence.EntityManager;
import javax.persistence.metamodel.EntityType;
import javax.persistence.metamodel.Metamodel;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

/**
 * 实体文件类型配置,
 * 配置实体类中文件的配置
 * @see FileResourceConfig
 * @author jtf
 * @since 0.0.1
 */
@Component
public class EntityFileResourceConfig implements FileResourceConfig {

    @Autowired
    protected EntityManager entityManager;

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Override
    public FileResourceConfigDTO[] getFileResourceConfigDTO() {
        // 实体元数据
        Metamodel metamodel = entityManager.getMetamodel();
        // 所有受管实体类型
        Set<EntityType<?>> entities = metamodel.getEntities();
        // 定义结果
        Set<FileResourceConfigDTO> result = new HashSet<>(entities.size());

        for (EntityType<?> entity : entities) {
            // 实体类型
            Class<?> javaType = entity.getJavaType();

            // 实体属性描述
            PropertyDescriptor[] propertyDescriptors = BeanUtils.getPropertyDescriptors(javaType);
            for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
                String name = propertyDescriptor.getName();
                try {
                    Field field = ReflectionUtils.findField(javaType, name);
                    if (Objects.isNull(field)) {
                        continue;
                    }
                    File annotation = field.getAnnotation(File.class);
                    if (Objects.nonNull(annotation)) {
                        // 增加
                        result.add(
                                new FileResourceConfigDTO(annotation.dirName(), annotation.fileType(), annotation.describe(),
                                        annotation.num())
                        );
                    }
                } catch (Exception ex) {
                    logger.warn("实体类注册文件：javaType:{},文件注册异常,字段名:{}", javaType, name, ex);
                }
            }
        }
        logger.info("实体类注册文件:{}", result);
        return result.toArray(new FileResourceConfigDTO[result.size()]);
    }

}
